<?php
namespace App\Api;

use App\Model\WALLETIOC;
use App\Model\WALLETTRADE;
use App\Model\WALLETWITHDRAW;
use PhalApi\Api;
use PhalApi\Exception;
use PhalApi\Exception\BadRequestException;
use PhalApi\Exception\InternalServerErrorException;
use App\Model\USER;
use App\Model\WALLETADDRESS;
use App\Common\WalletBase;
use App\Common\QRcode;


/**
 * 默认接口服务类
 *
 * @author: dogstar <chanzonghuang@gmail.com> 2014-10-04
 */

class Wallet extends BaseController
{

    public function getRules() {
        return
            [
                '*' => [
                    'token'  => ['name' => 'token',  'require' => true],
                    'api_version'  => ['name' => 'api_version',  'require' => true],
                    'app_version'  => ['name' => 'app_version',  'require' => true],
                ],
                'paySecret' => [
                    'password'  => ['name' => 'password',  'require' => true],
                    'code'  => ['name' => 'code',  'require' => false],
                    'phone'  => ['name' => 'phone',  'require' => false],
                ],
                'icoCost' => [
                    'ico'  => ['name' => 'ico',  'require' => true],
                    'num'  => ['name' => 'num',  'require' => true],
                    'address'  => ['name' => 'address',  'require' => false],
                ],
                'ico' => [
                    'ico'  => ['name' => 'ico',  'require' => true],
                ],
                'transaction' => [
                    'ico'  => ['name' => 'ico',  'require' => true],
                    'num'  => ['name' => 'num',  'require' => true],
                    'address'  => ['name' => 'address',  'require' => true],
                    'secret'  => ['name' => 'secret',  'require' => true],
                ],
                'transactionList' => [
                    'ico'  => ['name' => 'ico',  'require' => true],
                    'p'  => ['name' => 'p',  'require' => false],
                ],
                'supplyWallet' => [
                    'ico'  => ['name' => 'ico',  'require' => true],
                    'num'  => ['name' => 'num',  'require' => true],
                ],
                'SMS' => [
                    'phone'  => ['name' => 'phone',  'require' => true],
                ],

            ];
    }

    /**
     * 获取开通钱包协议内容
     * @return
     * author ge
     * date 2018/09/28
     */
    public function getProtocol()
    {
        return 'http://byb.world/index.php/Wallet/agreement';
    }

    /**
     * 钱包是否开通
     *
     * author ge
     * date 2018/09/28
     */

    public function checkWallet()
    {
        $model = new WALLETADDRESS();
        $data = $model->getWalletByToken($this->token);
        \PhalApi\DI()->logger->info('{接口:checkWallet},用户id:'.$data['uid'], ['params' => $this->get_params()]);
        if(!$data)
        {
            throw new BadRequestException('http://byb.world/index.php/Wallet/agreement');
        }
        return true;
    }

    /**
     * 创建钱包
     *
     * author ge
     * date 2018/09/28
     */
    public function createWallet()
    {
        $model = new USER();
        $uid = $model->getUserByToken($this->token);
        if(!$uid)
        {
            \PhalApi\DI()->logger->error('{接口:createWallet },用户不存在');
            throw new BadRequestException('用户不存在',1);
        }
        \PhalApi\DI()->logger->info('{接口:walletInfo},用户id:'.$uid['id'], ['params' => $this->get_params()]);
        $wallet = new WALLETADDRESS();
        $data = $wallet->getWalletByToken($this->token);

        if($data)
        {
            \PhalApi\DI()->logger->error('{接口:createWallet },钱包已创建');
            throw new BadRequestException('钱包已创建',2);
        }
        $data = WalletBase::userregister();

        $ico = new WALLETIOC();
        $ico = $ico->getIocs();
        //  使该地址支持目前所有币的操作
        foreach($ico as $v)
        {
            $data = WalletBase::deposit($data->id, $v['ico']);
        }
        if(empty($data->id))
        {
            \PhalApi\DI()->logger->error('{接口:createWallet },检查币种,deposit出错');
            throw new BadRequestException('创建失败',3);
        }

        $insert['create_time'] = time();
        $insert['wallet_id'] = $data->id;
        $insert['wallet_userid'] = $data->userId;
        $insert['wallet_address'] = $data->address;
        $insert['currency'] = $data->currency;
        $insert['uid'] = $uid['id'];
        $return = $wallet->insert($insert);
        if($return > 0)
        {
            \PhalApi\DI()->logger->info('{接口:createWallet},用户id:'.$uid['id'].',钱包创建成功', ['params' => $this->get_params()]);
            return true;
        }
    }

    /**
     * 钱包信息
     *
     * author ge
     * date 2018/09/28
     */

    public function walletInfo()
    {
        $model = new WALLETADDRESS();
        $data = $model->getWalletByToken($this->token);
        if(!$data['wallet_address'])
        {
            throw new BadRequestException('钱包地址不存在');
        }
        \PhalApi\DI()->logger->info('{接口:walletInfo},用户id:'.$data['uid'], ['params' => $this->get_params()]);
        if(!$data['qrcode'])
        {
            $filename = 'qrcode/'. $data['uid'] .'.png';
            QRcode::png($data['wallet_address'],$filename , 'L', 6, 2);
            $update['qrcode'] = '/'. $filename;
            $model->update($data['id'], $update);
            $qrcode = HOST . $update['qrcode'];
        }
        else
        {
            $qrcode = HOST . $data['qrcode'];
        }

        $ico_admin = new WALLETIOC();
        $ico_admin = $ico_admin->getAllIoc();
        $ico = '';
        foreach ($ico_admin as $v)
        {
            $ico .= $v['ico'] . '、';
        }
        $ico = trim($ico, '、');
        $return['address'] = $data['wallet_address'];
        $return['qrcode'] = $qrcode;
        $return['ico'] = $ico;
        return $return;
    }

    /**
     * 资产信息
     *
     * author ge
     * date 2018/09/28
     */
    public function accounts()
    {
        $model = new WALLETADDRESS();
        $wallet = $model->getWalletByToken($this->token);
        $data = WalletBase::accounts($wallet['wallet_userid']);
        \PhalApi\DI()->logger->info('{接口:accounts},用户id:'.$wallet['uid'], ['params' => $this->get_params()]);
        $sweet = $wallet['wallet'];
        $ico = [];
        $total = 0;
        $walletioc = new WALLETIOC();
        $icon_list = [];
        if(!empty($data->spotAccounts))
        {
            foreach($data->spotAccounts as $k => $v)
            {
                if($v->type == 'SPOT_AVAILABLE')
                {
                    $ico[$v->currency]['name'] = $v->currency;
                    $ico[$v->currency]['balance'] = $v->balance;
                    $ico_name = $walletioc->getIoc($v->currency);
                    $ico[$v->currency]['money'] = $v->balance * $ico_name['price'];
                    $ico[$v->currency]['icon'] = HOST . $ico_name['icon'];
                    $total += $v->balance * $ico_name['price'];
                    $icon_list[$v->currency] = $v->currency;
                }
            }
        }
        $ico_admin = new WALLETIOC();
        $ico_admin = $ico_admin->getAllIoc();
        $ico_list = [];
//var_dump($ico);die;
        foreach($ico_admin as $k => $v)
        {
            if(in_array($v['ico'], $icon_list))
            {
                $ico_list[$k]['name'] = $ico[$v['ico']]['name'];
                $ico_list[$k]['balance'] = strval(\APP\decimalNotation(round($ico[$v['ico']]['balance'], 5)));
                $ico_list[$k]['money'] = strval(\APP\decimalNotation(round($ico[$v['ico']]['money'], 2)));
                $ico_list[$k]['icon'] = $ico[$v['ico']]['icon'];
            }
            else
            {
                $ico_list[$k]['name'] = $v['ico'];
                $ico_list[$k]['balance'] = '0';
                $ico_list[$k]['money'] = '0';
                $ico_list[$k]['icon'] = HOST . $v['icon'];
            }
        }
        $ico = array_values($ico_list);
        $return['address'] = $wallet['wallet_address'];
        $return['total'] = strval(\APP\decimalNotation(round($total,2)));
        $return['sweet'] = $sweet;
        $return['sweet_icon'] = HOST . '/img/iconcandy.png';
        $return['ico'] = $ico;
        return $return;
    }

    /**
     * 代币流水
     */

    public function transactionList()
    {
        $model = new WALLETADDRESS();
        $wallet = $model->getWalletByToken($this->token);
        $data = WalletBase::accounts($wallet['wallet_userid']);

        \PhalApi\DI()->logger->info('{接口:transactionList},用户id:'.$wallet['uid'], ['params' => $this->get_params()]);

        $ico = new WALLETIOC();
        $ico = $ico->getIoc($this->ico);

        $return = [];
        $return['num'] = '0';
        $return['money'] = '0';
        foreach($data->spotAccounts as $k => $v)
        {
            if($v->currency == $this->ico && $v->type == 'SPOT_AVAILABLE')
            {
                $return['num'] = strval(\APP\decimalNotation(round($v->balance,5)));
                $return['money'] = strval(\APP\decimalNotation(round($v->balance*$ico['price'],2)));
                break;
            }
        }
        $trade = new WALLETTRADE();
        $p = $this->p ? $this->p : 1;
        $data = $trade->getTransaction($wallet['uid'], $this->ico, $p);
        if(!$data)
            return $return;
        foreach($data as $k => $v)
        {
            $return['transaction'][$k]['date'] = date('Y-m-d H:i:s', $v['create_time']);
            $return['transaction'][$k]['num'] = strval(\APP\decimalNotation(round($v['num'],5)));
            $return['transaction'][$k]['fromaddress'] = !empty($v['fromaddress']) ? $v['fromaddress'] : '';
            $return['transaction'][$k]['toaddress'] = !empty($v['toaddress']) ? $v['toaddress'] : '';
            $return['transaction'][$k]['status'] = '2';

            if($wallet['uid'] == $v['touid'])
            {
                $return['transaction'][$k]['in_out'] = 'in';
            }
            else
            {
                $return['transaction'][$k]['in_out'] = 'out';
            }
            switch($v['type'])
            {
                case self::RECHARGE:
                    $return['transaction'][$k]['type'] = '转入';
                    $return['transaction'][$k]['in_out'] = 'in';
                    break;
                case self::TRANSFER:
                    if($wallet['uid'] == $v['touid'])
                    {
                        $return['transaction'][$k]['type'] = '转入';
                    }
                    else
                    {
                        $return['transaction'][$k]['type'] = '转出';
                    }
                    break;
                case self::MINERFEE:
                    $return['transaction'][$k]['type'] = '矿工费';
                    break;
                case self::WHEEL:
                    $return['transaction'][$k]['type'] = '大转盘';
                    break;
                case self::ELEVEN:
                    $return['transaction'][$k]['type'] = '双十一抢币';
                    break;
            }
        }
        return $return;
    }

    /**
     * @return 代币详情
     * @throws BadRequestException
     * @throws InternalServerErrorException
     * @throws \Exception
     */

    public function ico()
    {
        $model = new WALLETADDRESS();
        $wallet = $model->getWalletByToken($this->token);

        $data = WalletBase::accounts($wallet['wallet_userid']);
        $return = '';
        foreach($data->spotAccounts as $k => $v)
        {
            if($v->currency == $this->ico)
            {
                $return = $v->balance;
                break;
            }
        }
        return $return;
    }

    /**
     * @return 获得矿工费
     * @throws BadRequestException
     * @throws InternalServerErrorException
     * @throws \Exception
     */

    public function icoCost()
    {
        $mb = mb_strlen($this->address,'utf-8');
        $st = strlen($this->address);
        if($mb != $st)
        {
            throw new BadRequestException('地址输入不正确!');
        }
        //$model = new WALLETADDRESS();
        //$wallet_check = $model->getWalletByAddress($this->address);
        $ico = new WALLETIOC();

        $ico = $ico->getIoc($this->ico);

        $model_wallet = new WALLETADDRESS();
        $wallet = $model_wallet->getWalletByToken($this->token);

        if($wallet['wallet_address'] == $this->address)
        {
            throw new BadRequestException('无法给自己钱包转账!');
        }
        if($this->num < $ico['lowest_money'])
        {
            throw new BadRequestException('最少交易'.$ico['lowest_money']);
        }
//        if($wallet_check)
//        {
//            $return = '0';
//        }
//        else
//        {
//            $return = '';
//            if($this->num * $ico['rate'] >= $ico['lowest_cost'] && $this->num * $ico['rate'] <= $ico['highest_cost'])
//            {
//                $return = $this->num * $ico['rate'];
//            }
//            elseif($this->num * $ico['rate'] <= $ico['lowest_cost'])
//            {
//                $return = $ico['lowest_cost'];
//            }
//            elseif($this->num * $ico['rate'] >= $ico['highest_cost'])
//            {
//                $return = $ico['highest_cost'];
//            }
//        }
        $return = '0.001';
//查找余额
        $data = WalletBase::accounts($wallet['wallet_userid']);
        $num = $cost = 0;
        foreach($data->spotAccounts as $k => $v)
        {
            if($v->currency == $this->ico && $v->type == 'SPOT_AVAILABLE')
            {
                $num = $v->balance;
            }
            if($v->currency == 'ETH' && $v->type == 'SPOT_AVAILABLE')
            {
                $cost = $v->balance;
            }
        }
//        if(bcsub($num, $this->num + $return, 10) < 0)
//        {
//            throw new BadRequestException('余额不足!');
//        }
        if($num < $this->num)
        {
            throw new BadRequestException('余额不足!');
        }
        elseif($cost < $return)
        {
            throw new BadRequestException('矿工费'.round($return,5).'ETH,钱包余额不足！请充值ETH');
        }
        if($this->ico == 'ETH')
        {
            if(bcsub($num, $this->num + $return, 10) < 0)
            {
                throw new BadRequestException('余额不足!');
            }
        }
        return \APP\decimalNotation(round($return,5)) . ' ETH';

    }

    /**
     * @return 转账
     * @throws BadRequestException
     * @throws InternalServerErrorException
     * @throws \Exception
     */

    public function transaction()
    {
        $mb = mb_strlen($this->address,'utf-8');
        $st = strlen($this->address);
        if($mb != $st)
        {
            throw new BadRequestException('地址输入不正确!');
        }
        $model = new WALLETADDRESS();
        $wallet = $model->getWalletByToken($this->token);
        if($wallet['paymentpwd'] != md5($this->secret))
        {
            throw new BadRequestException('支付密码错误');
        }

        if(!$wallet['wallet_userid'] || !$wallet['wallet_address'])
        {
            throw new BadRequestException('您的钱包不存在');
        }
        /**
         * 验证余额等条件
         */
        try
        {
            $icocost = $this->icoCost();
        }
        catch (Exception $e)
        {
            throw new BadRequestException($e->getMessage());
        }

        $walletaddress = new WALLETWITHDRAW();
        $isSystemAddress = $model->getWalletByAddress($this->address);

        /**
         * 获取余额
         */
        $data = WalletBase::accounts($wallet['wallet_userid']);
        $balance = $eth = 0;
        foreach($data->spotAccounts as $k => $v)
        {
            if($v->currency == $this->ico && $v->type == 'SPOT_AVAILABLE')
            {
                $balance = $v->balance;
            }
            if($v->currency == 'ETH' && $v->type == 'SPOT_AVAILABLE')
            {
                $eth = $v->balance;
            }
        }

        /**
         * 内部交易
         */
        if($isSystemAddress)
        {
            /**
             * 获取余额
             */
            $data = WalletBase::accounts($isSystemAddress['wallet_userid']);
            $tobalance = 0;
            foreach($data->spotAccounts as $k => $v)
            {
                if($v->currency == $this->ico && $v->type == 'SPOT_AVAILABLE')
                {
                    $tobalance = $v->balance;
                }
            }

            $transfer = WalletBase::transfer($this->num, $this->ico, $wallet['wallet_userid'], $isSystemAddress['wallet_userid']);

            if(!empty($transfer->from->id))
            {
                \PhalApi\DI()->logger->info('{接口:transaction 内部交易},用户id:'.$wallet['uid'].'向用户id'.$isSystemAddress['uid'].',转账数量:'.$this->num.',币种:'.$this->ico.',交易成功');
                $trade = new WALLETTRADE();
                $insert = [];
                $insert['type'] = self::TRANSFER;
                $insert['balance'] = $balance - $this->num;
                $insert['tobalance'] = $tobalance + $this->num;
                $insert['num'] = $this->num;
                $insert['fromuid'] = $wallet['uid'];
                $insert['touid'] = $isSystemAddress['uid'];
                $insert['ico'] = $this->ico;
                $insert['fromaddress'] = $wallet['wallet_address'];
                $insert['toaddress'] = $this->address;
                $insert['style'] = self::INTERNALTRANSFER;
                $insert['create_time'] = time();
                $trade->insert($insert);
                $this->gas($eth, $wallet['wallet_userid'], $wallet['uid'], $wallet['wallet_address']);
                return [true, 'msg' => '交易成功'];
            }
            \PhalApi\DI()->logger->error('{接口:transaction 内部交易},用户id:'.$wallet['uid'].',交易失败:'.$transfer->message);
            throw new BadRequestException('交易失败');
        }

        /**
         * 外部交易
         */
        $addressid = $walletaddress->getAddressid($this->ico, $wallet['wallet_userid'], $this->address);
        if(!$addressid)
        {
            // 获取转账用的地址id
            $addressid = WalletBase::withdraw($wallet['wallet_userid'], $this->ico, $this->address);
            if(!empty($addressid->id))
            {
                \PhalApi\DI()->logger->info('{接口:transaction 外部交易},用户id:'.$wallet['uid'].',首次获取addressid,值:'.$addressid->id, ['params' => $this->get_params()]);
                $addressid = $addressid->id;
                $insert = [];
                $insert['address_id'] = $addressid;
                $insert['ico'] = $this->ico;
                $insert['from_wallet_user_id'] = $wallet['wallet_userid'];
                $insert['toaddress'] = $this->address;
                $walletaddress->insert($insert);
            }
            else
            {
                throw new BadRequestException($addressid->message);
                \PhalApi\DI()->logger->error('{接口:transaction 外部交易},用户id:'.$wallet['uid'].',首次获取addressid失败!'.$addressid->message, ['params' => $this->get_params()]);
            }
        }
        else
        {
            $addressid = $addressid['address_id'];
        }
        // 外部交易
        $icocost = trim($icocost, ' ETH');
        $result = WalletBase::withdrawRequest($this->num, $this->ico, $wallet['wallet_userid'], $addressid);

        if(isset($result->status) && $result->status == 'SUBMITTED')
        {
            $check = WalletBase::check($result->id);              //审核该交易
            if($check->result == true)
            {
                \PhalApi\DI()->logger->info('{接口:transaction 外部交易},用户id:'.$wallet['uid'], '交易id' . $result->id . '审核结果: 成功!交易金额:'.$this->num.',gas费:'.$icocost.',转入地址:'.$this->address);
                $trade = new WALLETTRADE();
                $insert = [];
                $insert['type'] = self::TRANSFER;
                $insert['balance'] = $balance - $this->num;
                $insert['num'] = $this->num;
                $insert['gas'] = $icocost;
                $insert['fromuid'] = $wallet['uid'];
                $insert['ico'] = $this->ico;
                $insert['fromaddress'] = $wallet['wallet_address'];
                $insert['toaddress'] = $this->address;
                $insert['create_time'] = time();
                $insert['style'] = self::EXTERNALTRANSFER;;
                $trade->insert($insert);
                $this->gas($eth, $wallet['wallet_userid'], $wallet['uid'], $wallet['wallet_address']);
            }
            else
            {
                \PhalApi\DI()->logger->error('{接口:transaction 外部交易},用户id:'.$wallet['uid'], '交易id' . $result->id . '审核结果: 失败:'.$check->message);
                throw new BadRequestException('交易审核失败');
            }
        }
        else
        {
            \PhalApi\DI()->logger->error('{接口:transaction 外部交易},用户id:'.$wallet['uid'].',交易失败,message:'.$result->message, ['params' => $this->get_params()]);
            throw new BadRequestException('交易失败');
        }
        return [true, 'msg' => '交易成功'];
    }

    /**
     * 修改支付密码 发送短信
     */
    public function sms()
    {
        $model = new USER();
        $user = $model->getUserByToken($this->token);
        if($user['telphone'] != $this->phone)
        {
            throw new BadRequestException('手机号错误');
        }
        $result = \App\sendSms($this->phone);
        if($result['Code'] == 'OK')
        {
            \PhalApi\DI()->logger->info('{接口:SMS},用户id:'.$user['id'], '短信发送成功');
            return true;
        }
        else
        {
            throw new BadRequestException('发送失败');
        }
    }

    /**
     * @return 修改支付密码
     * @throws BadRequestException
     * @throws InternalServerErrorException
     * @throws \Exception
     */

    public function paySecret()
    {
        if($this->code)
        {
            $code = \PhalApi\DI()->cache->get('sms'.$this->phone);
            if(!$code)
            {
                throw new BadRequestException('验证码超时,请重新获取!');
            }
            if($this->code != $code)
            {
                throw new BadRequestException('验证码错误');
            }
            \PhalApi\DI()->cache->delete('sms'.$this->phone);
        }
        $model = new WALLETADDRESS();
        $wallet = $model->getWalletByToken($this->token);

        $data['paymentpwd'] = md5($this->password);
        $data['update_time'] = time();
        if($model->update($wallet['id'], $data))
        {
            \PhalApi\DI()->logger->info('{接口:paySecret},用户id:'.$wallet['uid'], '支付密码更新成功');
            return [true, 'msg' => '密码设置成功'];
        }
        else
        {
            \PhalApi\DI()->logger->error('{接口:paySecret},用户id:'.$wallet['uid'].',支付密码更新失败', ['params' => $this->get_params()]);
            throw new BadRequestException('密码设置失败');
        }
    }

    /**
     * @return 是否设置支付密码
     * @throws BadRequestException
     * @throws InternalServerErrorException
     * @throws \Exception
     */

    public function setPaySecret()
    {
        $model = new WALLETADDRESS();
        $wallet = $model->getWalletByToken($this->token);
        if(!$wallet['paymentpwd'])
        {
            throw new BadRequestException('没有设置支付密码');
        }
        return true;
    }
    //使该wallet支持token  发的token转币到帐号使用
    public function supplyWallet()
    {
        $data = WalletBase::currencies($this->ico, '0x81926594db5E008bAa5Ae1E6576260de45F45cb2', $this->num);
        var_dump($data);die;
    }

    /**
     * 收取gas费
     */
    public function gas($eth, $wallet_userid, $uid, $wallet_address)
    {
        /**
         * gas费转入公司钱包地址
         */
        $transfer = WalletBase::transfer(self::GASFEE, 'ETH', $wallet_userid, self::OFFICIALUSERID);
        if(!empty($transfer->from->id))
        {
            $trade = new WALLETTRADE();
            $insert = [];
            $insert['type'] = self::MINERFEE;
            if($this->ico == 'ETH')
            {
                $insert['balance'] = $eth - self::GASFEE - $this->num;
            }
            else
            {
                $insert['balance'] = $eth - self::GASFEE;
            }

            $insert['num'] = self::GASFEE;
            $insert['fromaddress'] = $wallet_address;
            $insert['fromuid'] = $uid;
            $insert['touid'] = self::USERID;
            $insert['ico'] = 'ETH';
            //$insert['toaddress'] = self::GASADDRESS;
            $insert['style'] = self::INTERNALTRANSFER;;
            $insert['create_time'] = time();
            $trade->insert($insert);
        }
        else
        {
            \PhalApi\DI()->logger->error('{接口:transaction 转入gas费},用户id:'.$wallet['uid'].',交易失败:'.$transfer->message);
            throw new BadRequestException('交易失败');
        }
    }
}